/*
 *  test.c
 *
 *  Created on: 2010-5-23
 *      Author: liuyond
 *      Abstract: this file will implement some test functions.
 */
#include "cpu.h"
#include <assert.h>
#include <stdio.h>

/**
 * cpu_test - test all the interface which modify cpu's context
 * @cpu:    point to the cpu's context
 * @return: no return
 */
void cpu_test(cpu_t *cpu)
{
	int seg = DS, off = 0x1000;
	
	// test the interface that modify cpu's register
	cpu_set_regb(cpu, AL, 0x12);
	cpu_set_regb(cpu, CL, 0x12);
	cpu_set_regb(cpu, DL, 0x12);
	cpu_set_regb(cpu, BL, 0x12);
	cpu_set_regb(cpu, AH, 0x12);
	cpu_set_regb(cpu, CH, 0x12);
	cpu_set_regb(cpu, DH, 0x12);
	cpu_set_regb(cpu, BH, 0x12);
	assert(cpu_get_regb(cpu, AL) == 0x12);
	assert(cpu_get_regb(cpu, CL) == 0x12);
	assert(cpu_get_regb(cpu, DL) == 0x12);
	assert(cpu_get_regb(cpu, BL) == 0x12);
	assert(cpu_get_regb(cpu, AH) == 0x12);
	assert(cpu_get_regb(cpu, CH) == 0x12);
	assert(cpu_get_regb(cpu, DH) == 0x12);
	assert(cpu_get_regb(cpu, BH) == 0x12);
	cpu_set_regb(cpu, AL, 0x34);
	cpu_set_regb(cpu, CL, 0x34);
	cpu_set_regb(cpu, DL, 0x34);
	cpu_set_regb(cpu, BL, 0x34);
	cpu_set_regb(cpu, AH, 0x34);
	cpu_set_regb(cpu, CH, 0x34);
	cpu_set_regb(cpu, DH, 0x34);
	cpu_set_regb(cpu, BH, 0x34);
	assert(cpu_get_regb(cpu, AL) == 0x34);
	assert(cpu_get_regb(cpu, CL) == 0x34);
	assert(cpu_get_regb(cpu, DL) == 0x34);
	assert(cpu_get_regb(cpu, BL) == 0x34);
	assert(cpu_get_regb(cpu, AH) == 0x34);
	assert(cpu_get_regb(cpu, CH) == 0x34);
	assert(cpu_get_regb(cpu, DH) == 0x34);
	assert(cpu_get_regb(cpu, BH) == 0x34);
	cpu_set_reg(cpu, AX, 0x1234);
	cpu_set_reg(cpu, CX, 0x1234);
	cpu_set_reg(cpu, DX, 0x1234);
	cpu_set_reg(cpu, BX, 0x1234);
	cpu_set_reg(cpu, SP, 0x1234);
	cpu_set_reg(cpu, BP, 0x1234);
	cpu_set_reg(cpu, SI, 0x1234);
	cpu_set_reg(cpu, DI, 0x1234);
	assert(cpu_get_reg(cpu, AX) == 0x1234);
	assert(cpu_get_reg(cpu, CX) == 0x1234);
	assert(cpu_get_reg(cpu, DX) == 0x1234);
	assert(cpu_get_reg(cpu, BX) == 0x1234);
	assert(cpu_get_reg(cpu, SP) == 0x1234);
	assert(cpu_get_reg(cpu, BP) == 0x1234);
	assert(cpu_get_reg(cpu, SI) == 0x1234);
	assert(cpu_get_reg(cpu, DI) == 0x1234);
	cpu_set_reg(cpu, CS, 0x1234);
	cpu_set_reg(cpu, SS, 0x1234);
	cpu_set_reg(cpu, DS, 0x1234);
	cpu_set_reg(cpu, ES, 0x1234);
	assert(cpu_get_reg(cpu, CS) == 0x1234);
	assert(cpu_get_reg(cpu, SS) == 0x1234);
	assert(cpu_get_reg(cpu, DS) == 0x1234);
	assert(cpu_get_reg(cpu, ES) == 0x1234);
	cpu_set_flag(cpu, CF, 1);
	cpu_set_flag(cpu, PF, 1);
	cpu_set_flag(cpu, AF, 1);
	cpu_set_flag(cpu, ZF, 1);
	cpu_set_flag(cpu, SF, 1);
	cpu_set_flag(cpu, TF, 1);
	cpu_set_flag(cpu, IF, 1);
	cpu_set_flag(cpu, DF, 1);
	cpu_set_flag(cpu, OF, 1);
	assert(cpu_get_flag(cpu, CF));
	assert(cpu_get_flag(cpu, PF));
	assert(cpu_get_flag(cpu, AF));
	assert(cpu_get_flag(cpu, ZF));
	assert(cpu_get_flag(cpu, SF));
	assert(cpu_get_flag(cpu, TF));
	assert(cpu_get_flag(cpu, IF));
	assert(cpu_get_flag(cpu, DF));
	assert(cpu_get_flag(cpu, OF));
	cpu_set_flag(cpu, CF, 0);
	cpu_set_flag(cpu, PF, 0);
	cpu_set_flag(cpu, AF, 0);
	cpu_set_flag(cpu, ZF, 0);
	cpu_set_flag(cpu, SF, 0);
	cpu_set_flag(cpu, TF, 0);
	cpu_set_flag(cpu, IF, 0);
	cpu_set_flag(cpu, DF, 0);
	cpu_set_flag(cpu, OF, 0);
	assert(!cpu_get_flag(cpu, CF));
	assert(!cpu_get_flag(cpu, PF));
	assert(!cpu_get_flag(cpu, AF));
	assert(!cpu_get_flag(cpu, ZF));
	assert(!cpu_get_flag(cpu, SF));
	assert(!cpu_get_flag(cpu, TF));
	assert(!cpu_get_flag(cpu, IF));
	assert(!cpu_get_flag(cpu, DF));
	assert(!cpu_get_flag(cpu, OF));
	fprintf(stdout, "register interface success!\n");
	// test the interface that modify cpu's memory
	cpu_set_mem_byte(cpu, seg, off, 0x12);
	assert(cpu_get_mem_byte(cpu, seg, off) == 0x12);
	cpu_set_mem_word(cpu, seg, off, 0x1234);
	assert(cpu_get_mem_word(cpu, seg, off) == 0x1234);
	cpu_set_mem_dword(cpu, seg, off, 0x12345678);
	assert(cpu_get_mem_dword(cpu, seg, off) == 0x12345678);
	// setup stack register
	cpu_set_reg(cpu, SP, 0x1000);
	cpu_push_mem_word(cpu, 0x1234);
	cpu_push_mem_word(cpu, 0x5678);
	cpu_push_mem_dword(cpu, 0x12345678);
	assert(cpu_pop_mem_dword(cpu) == 0x12345678);
	assert(cpu_pop_mem_word(cpu) == 0x5678);
	assert(cpu_pop_mem_word(cpu) == 0x1234);
	fprintf(stdout, "memory interface success!\n");
}

void cpu_show_regs(cpu_t *cpu)
{
	fprintf(stdout, "AX = %04X BX = %04X CX = %04X DX = %04X\n",
			cpu->regs[AX], cpu->regs[BX], cpu->regs[CX], cpu->regs[DX]);
	fprintf(stdout, "SP = %04X BP = %04X SI = %04X DI = %04X\n",
			cpu->regs[SP], cpu->regs[BP], cpu->regs[SI], cpu->regs[DI]);
}

void cpu_show_segs(cpu_t *cpu)
{
	fprintf(stdout, "CS = %04X SS = %04X DS = %04X ES = %04X\n",
			cpu->segs[CS], cpu->segs[SS], cpu->segs[DS], cpu->segs[ES]);
}

void cpu_show_flags(cpu_t *cpu)
{
	fprintf(stdout, "%s  ", !cpu_get_flag(cpu, OF) ? "NV" : "OV");
	fprintf(stdout, "%s  ", !cpu_get_flag(cpu, DF) ? "UP" : "DN");
	fprintf(stdout, "%s  ", !cpu_get_flag(cpu, IF) ? "DI" : "EI");
	fprintf(stdout, "%s  ", !cpu_get_flag(cpu, SF) ? "PL" : "NG");
	fprintf(stdout, "%s  ", !cpu_get_flag(cpu, ZF) ? "NZ" : "ZR");
	fprintf(stdout, "%s  ", !cpu_get_flag(cpu, AF) ? "NA" : "AC");
	fprintf(stdout, "%s  ", !cpu_get_flag(cpu, PF) ? "PO" : "PE");
	fprintf(stdout, "%s\n", !cpu_get_flag(cpu, CF) ? "NC" : "CY");
}

void cpu_show_all(cpu_t *cpu)
{
	cpu_show_regs(cpu);
	cpu_show_segs(cpu);
	cpu_show_flags(cpu);
	fprintf(stdout, "\nIP = %X\n", cpu->ip);
}
